class jsonSchemaToolHandle {
  constructor(instance) {
    this.instance = instance; // this指向 实例对象
  }
  /**
   * 判断当前节点是否是根节点或叶子节点
   * @param {*} nodeName
   * @returns
   */
  headerExist(nodeName) {
    return nodeName != undefined;
  }
  /**
   * 判断当前节点是否是临时节点
   * @param {*} schema
   */
  isTempNode(schema) {
    return schema["x-tmp-pending-properties"] != undefined;
  }
  /**
   * 判断当前的节点是不是非叶子节点
   * @param {*} schema
   * @returns
   */
  contentExist(schema) {
    return this.isComplexType(schema, 0, 1, 2, 4);
  }
  /**
   * 判断当前节点是叶子节点
   * @param {*} currentIndex // 当前节点的索引
   * @param {*} schema // 当前节点的数据结构
   * @returns
   */
  isLeafNode(currentIndex, schema) {
    return currentIndex != 1 && !this.contentExist(schema);
  }
  /**
   * 判断当前节点是非叶子节点非根节点
   * @param {*} currentIndex
   * @param {*} schema
   * @returns
   */
  isNotLeafAndRootNode(currentIndex, schema) {
    return currentIndex != 1 && this.contentExist(schema);
  }
  /**
   * 判断当前节点的数据类型
   * @param {*} schema 当前节点的数据结构
   * @returns
   */
  getCurrentType(schema) {
    if (
      schema.type == "array" ||
      (Array.isArray(schema.type) &&
        schema.type.length == 2 &&
        schema.type.includes("array"))
    ) {
      // 数组类型
      return 0;
    } else if (
      (schema.type == "object" &&
        !schema.hasOwnProperty("patternProperties")) ||
      (Array.isArray(schema.type) &&
        schema.type.length == 2 &&
        schema.type.includes("object") &&
        !schema.hasOwnProperty("patternProperties"))
    ) {
      // 对象类型[字典也是object类型，因为对字典进行了特殊处理，所以这里判断时要进一步区分]
      return 1;
    } else if (schema.$ref != undefined) {
      // 引用类型
      return 2;
    } else if (
      (schema.type == "object" && schema.hasOwnProperty("patternProperties")) ||
      (Array.isArray(schema.type) &&
        schema.type.length == 2 &&
        schema.type.includes("object") &&
        schema.hasOwnProperty("patternProperties"))
    ) {
      // 字典
      return 4;
    } else {
      // 其他类型 包含string,integer,number,boolean,null,any
      return 3;
    }
  }
  /**
   * 判断当前的节点数据类型是不是属于数组、对象、引用类型、组合模式之一
   * @param {*} schema 当前节点的数据结构
   * @param {*} types 复杂类型 包含array,object,ref,组合模式
   */
  isComplexType(schema, ...types) {
    for (let value of types) {
      if (this.getCurrentType(schema) == value) {
        return true;
      }
    }
    return false;
  }

  /**
   * 字典类型key的映射
   * @returns
   */
  dictKeyMap(type) {
    let r = {
      integer: "^\\d+$",
      string: "^[a-zA-Z_][a-zA-Z0-9_]*$",
    }[type];
    return r;
  }

  /**
   * 验证是否为有效的字典类型Schema
   * @param {Object} schema - 要验证的JSON Schema对象
   */
  isDictType(schema) {
    // 检查类型是否为"object"或包含"object"的两种类型数组
    const isObjectType =
      schema.type === "object" ||
      (Array.isArray(schema.type) &&
        schema.type.length === 2 &&
        schema.type.includes("object"));

    // 检查是否有patternProperties属性
    const hasPatternProperties = schema.hasOwnProperty("patternProperties");

    // 如果不是对象类型或者没有patternProperties，则抛出错误
    if (!isObjectType || !hasPatternProperties) {
      return false;
    }
    return true;
  }

  /**
   * 获取字典类型的key
   */
  getDictKey(schema) {
    const firstKeyPattern = Object.keys(schema.patternProperties)[0];
    return firstKeyPattern;
  }

  /**
   * 获取字典类型的value
   */
  getDictValue(schema) {
    const firstValueSchema = Object.values(schema.patternProperties)[0];
    return firstValueSchema;
  }

  /**
   * 获取字典类型的key和value类型
   * @param {*} schema
   */
  getDictKeyAndValueType(schema) {
    const result = {
      keyType: null,
      valueType: null,
    };

    // 提取键类型（通过 patternProperties 的正则推断）
    const keyPatterns = Object.keys(schema.patternProperties);
    if (keyPatterns.includes("^\\d+$")) {
      result.keyType = "integer"; // 数字键
    } else if (keyPatterns.includes("^[a-zA-Z_][a-zA-Z0-9_]*$")) {
      result.keyType = "string"; // 字符串键
    } else {
      result.keyType = "unknown"; // 其他模式
    }

    // 提取值类型（取第一个 patternProperties 的 type）
    const firstValueSchema = Object.values(schema.patternProperties)[0];
    result.valueType = this.getTypeTextColor(firstValueSchema);
    return result;
  }
  /**
   * 获取数据类型对应的文本颜色
   * @param {*} schema jsonSchema数据
   * @returns
   */
  getTypeTextColor(schema) {
    if (schema.type == "array") {
      return "array";
    } else if (
      schema.type == "object" &&
      !schema.hasOwnProperty("patternProperties")
    ) {
      return "object";
    } else if (schema.type == "string") {
      return "string";
    } else if (schema.type == "integer") {
      return "integer";
    } else if (schema.type == "number") {
      return "number";
    } else if (schema.type == "boolean") {
      return "boolean";
    } else if (schema.type == "null") {
      return "null";
    } else if (this.isDictType(schema)) {
      return "dictionary";
    } else if (schema.$ref != undefined) {
      return "ref";
    } else if (Array.isArray(schema.type) && schema.type.includes("null")) {
      return schema.type.length == 2 ? schema.type[0] : "any";
    }
  }
  /**
   * 获取当前schema的properties属性
   * @param {*} schema
   * @returns
   */
  schemaProperties(schema) {
    if (schema["x-apifox-orders"] != undefined) {
      return schema["x-apifox-orders"];
    } else {
      return schema.properties;
    }
  }
  /**
   * 判断当前遍历的是自己的属性还是引用的
   * @param {*} schema
   * @returns
   */
  isProperties(schema) {
    return (
      schema["x-apifox-orders"].length > Object.keys(schema.properties).length
    );
  }
  /**
   * 获取当前schema的property属性，适用于使用了引用类型的数据
   */
  schemaPropertiesRef(schema, key) {
    if (
      schema["x-apifox-refs"] != undefined &&
      schema["x-apifox-refs"][key] != undefined
    ) {
      return { value: schema["x-apifox-refs"][key], sign: 1 };
    } else {
      if (schema.properties[key]["$ref"]) {
        return { value: schema.properties[key], sign: 2 };
      } else {
        return { value: schema.properties[key] };
      }
    }
  }
  /**
   * 获取schema中引用的json数据
   * @param {*} jsonSchema 全量jsonSchema数据
   * @param {*} ref 引用的ref值
   * @returns
   */
  analysisSchemaRef(jsonSchema, ref) {
    let refData = this.recurForJsonSchema(
      jsonSchema,
      ref.split("/")[1] == "globalDefinitions" ? "globalDataId" : "modelDataId",
      ref.split("/")[2]
    );
    return {
      name: refData.name,
      value: JSON.parse(refData.data.jsonSchemaData),
    };
  }
  /**
   * 递归编辑引用的数据结构的节点
   * @param {*} arr 全量的jsonSchema数据
   * @param {*} fieldFlag 全局还是局部的字段标志，对应结构体中的modelDataId和globalDataId
   * @param {*} id 目标数据结构
   * @returns
   */
  recurForJsonSchema(arr, fieldFlag, id) {
    // 递归遍历数据获取当前实体名称
    let node = null;
    arr.forEach((item) => {
      let temp = { ...item };
      if (temp.children && temp.children.length > 0) {
        if (temp.id == id && temp.data[fieldFlag]) {
          node = temp;
        } else {
          let result = this.recurForJsonSchema(temp.children, fieldFlag, id);
          if (result) {
            node = result;
          }
        }
      } else {
        if (temp.id == id && temp.data[fieldFlag]) {
          node = temp;
        }
      }
    });
    return node;
  }

  /**
   * 根据节点ID获取其所有祖先节点ID数组（从根到父节点的顺序）
   * @param {Array} treeData 树结构数据
   * @param {number} nodeId 要查找的节点ID
   * @returns {Array} 祖先节点ID数组，如未找到返回空数组
   */
  getAncestorIds(treeData, nodeId) {
    // 用于记录查找路径的栈
    const path = [];

    // 递归查找函数
    function findNode(nodes, targetId) {
      for (const node of nodes) {
        // 将当前节点加入路径（后续如果匹配失败会弹出）
        path.push(node.id);

        // 如果找到目标节点，返回true终止查找
        if (node.id == targetId) return true;

        // 如果有子节点且子节点中找到目标，也返回true
        if (node.children && node.children.length > 0) {
          if (findNode(node.children, targetId)) return true;
        }

        // 当前分支未找到，弹出当前节点
        path.pop();
      }
      return false;
    }

    // 执行查找
    findNode(treeData, nodeId);

    // 移除目标节点自身（只需要祖先）
    if (path.length > 0) path.pop();

    return path;
  }
  /**
   * 判断是否是同级属性
   * @param {*} schema
   * @param {*} property
   */
  isSameLevelProperty(schema, property) {
    return (
      schema["x-apifox-refs"] != undefined &&
      schema["x-apifox-refs"][property] != undefined
    );
  }
  /**
   * 判断当前属性是否必填
   * @param {*} requiredArr 父节点的必填数组
   * @param {*} property 当前属性
   * @returns
   */
  isRequired(schema, property) {
    return schema["required"] ? schema["required"].includes(property) : false;
  }
  /**
   * 判断当前属性是否允许为NULL
   * @param {*} schema
   */
  isNullAble(schema) {
    return (
      schema.type &&
      ((Array.isArray(schema.type) && schema.type.includes("null")) ||
        schema.type == "null")
    );
  }

  /**
   * 判断当前属性是否允许为NULL
   * 引用类型 null类型 any类型 不允许设置NULL
   * @param {*} schema
   */
  displayIsNullAble(schema) {
    if (Array.isArray(schema.type)) {
      return this.getOriginalTypeWhenTypeIncludeMulti(schema.type) != "any";
    } else {
      return !(this.isComplexType(schema, 2) || schema.type == "null");
    }
  }

  /**
   * 判断当前节点是否显示更多按钮(array的items)
   * @param {*} schema
   */
  hasMoreBtn(schema, currentIndex, isArrayItems = false) {
    if (currentIndex == 1) {
      return this.isComplexType(schema, 1, 2);
    } else {
      if (!isArrayItems) {
        return this.isComplexType(schema, 1);
      } else {
        return this.isComplexType(schema, 1, 2, 4);
      }
    }
  }
  /**
   * 判断当前节点是否显示添加按钮（array的items）
   * @param {*} schema
   */
  hasAddBtn(schema) {
    return this.isComplexType(schema, 1, 2, 4);
  }
  /**
   * 判断当前节点是否拥有添加相邻节点的按钮
   * @param {*} schema
   * @param {*} currentIndex
   */
  hasAddAdjacentNode(schema, currentIndex) {
    if (currentIndex == 1) {
      return false;
    } else {
      return true;
    }
  }
  /**
   * 判断当前节点是否拥有添加子节点的按钮
   * @param {*} schema
   * @param {*} currentIndex
   */
  hasAddChildNode(schema, currentIndex) {
    if (currentIndex == 1) {
      return this.isComplexType(schema, 1, 2);
    } else {
      if (schema.type != undefined) {
        // if (schema.items != undefined) {
        //     return this.isComplexType(schema.items, 1, 2)
        // } else {
        //     return this.isComplexType(schema, 1)
        // }
        return this.isComplexType(schema, 1);
      } else {
        if (this.isComplexType(schema, 2)) {
          return true;
        } else {
          return false;
        }
      }
    }
  }
  /**
   * 判断当前节点是否同时拥有添加相邻节点和添加子节点两个按钮
   * @param {*} schema
   * @param {*} currentIndex
   */
  hasAllAddNode(schema, currentIndex) {
    if (currentIndex == 1) {
      return false;
    } else {
      // 只有非根节点的对象类型和引用类型才有添加相邻节点和添加子节点的按钮
      return this.isComplexType(schema, 1, 2);
    }
  }
  /**
   * 关闭popover
   * @param {*} ref 关闭指定的popover
   */
  closePopover(ref) {
    Object.keys(this.instance.$refs).forEach((key) => {
      if (ref) {
        // 关闭其他的popover，保留当前的popover
        if (
          key != ref &&
          this.instance.$refs[key] &&
          this.instance.$refs[key].showPopper
        ) {
          // 检测到有其他popover显示时，将其他popover关闭
          this.instance.$nextTick(() => {
            this.instance.$refs[key].doClose();
          });
        }
      } else {
        // 关闭所有的popover
        if (this.instance.$refs[key] && this.instance.$refs[key].showPopper) {
          this.instance.$nextTick(() => {
            this.instance.$refs[key].doClose();
          });
        }
      }
    });
  }
  /**
   * 更新popover弹框的位置，防止超出界面导致出现滚动条不美观
   * @param {*} popoverRef
   */
  updatePopoverPos(popoverRef) {
    this.instance.$nextTick(() => {
      const popoverDom = this.instance.$refs[popoverRef].$refs.popper;
      // 设置级联面板的位置在按钮右侧,并且不会超出屏幕范围
      const x = popoverDom.offsetLeft;
      const y = popoverDom.offsetTop;
      const panelHeight = popoverDom.offsetHeight;
      if (y + panelHeight > window.innerHeight) {
        // 如果面板底部超出屏幕，则将面板位置调整到按钮上方
        this.instance.$refs[popoverRef].$refs.popper.style.top =
          y - panelHeight + 100 + "px";
      } else {
        // 否则，将面板位置显示在按钮下方
        // this.instance.$refs[popoverRef].$refs.popper.style.top = y - 50 + "px";
      }
      // 设置级联面板的位置
      this.instance.$refs[popoverRef].$refs.popper.style.position = "absolute";
      this.instance.$refs[popoverRef].$refs.popper.style.left = x + "px";
    });
  }
  /**
   * 判断当前树节点是文件夹还是模型
   * @param {*} nodeData
   */
  isFolder(nodeData) {
    return nodeData["type"] == 0;
  }
  /**
   * 判断当前的值是否为空
   * @param {*} value
   */
  isEmptyValue(value) {
    return value !== null && value !== 0 && value.trim() == "";
  }
  /**
   * 判断当前的对象是否为空对象
   * @param {*} obj
   * @returns
   */
  isEmptyObject(obj) {
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) return false;
    }
    return true;
  }
  /**
   * 判断当前同层级下是否有同名的属性
   * @param {*} parentSchema
   * @param {*} currentName
   * @returns
   */
  isCurrentNameRepeat(parentSchema, currentName) {
    const properties = JSON.parse(JSON.stringify(parentSchema.properties));
    const r =
      Object.keys(properties).filter((item) => item == currentName).length > 0;

    return (
      Object.keys(properties).filter((item) => item == currentName).length > 0
    );
  }
  /**
   * 修改节点名称后，更新当前节点的schema数据
   * @param {*} currentSchema
   * @param {*} key
   */
  updateSchema(parentSchema, oldKey, newKey) {
    const newSchema = { ...parentSchema }; // 浅拷贝父对象
    newSchema.properties = { ...parentSchema.properties }; // 拷贝 properties

    if (oldKey in newSchema.properties) {
      newSchema.properties[newKey] = newSchema.properties[oldKey]; // 复制引用
      delete newSchema.properties[oldKey]; // 删除旧键（操作的是新对象）
    }

    // 处理 x-apifox-orders 和 required（同样需不可变）
    if (newSchema["x-apifox-orders"]) {
      newSchema["x-apifox-orders"] = parentSchema["x-apifox-orders"].map(
        (item) => (item === oldKey ? newKey : item)
      );
    }
    if (newSchema.required) {
      newSchema.required = parentSchema.required.map((item) =>
        item === oldKey ? newKey : item
      );
    }

    return newSchema; // 返回全新对象
  }
  /**
   * 获取节点开头空白的宽度
   * @param {*} index
   * @param {*} schema
   * @param {*} writable
   */
  getEmptyWidth(currentIndex, currentSchema, writable, isArrayItems) {
    if (writable) {
      // 非引用
      if (currentIndex == 1) {
        // 根节点
        if (this.isComplexType(currentSchema, 3)) {
          // 叶子节点
          return 32;
        } else {
          // 非叶子节点
          if (isArrayItems) {
            return 32;
          } else {
            return 16;
          }
        }
      } else {
        // 非根节点
        if (this.isComplexType(currentSchema, 3)) {
          // 叶子节点
          return 16 * currentIndex;
        } else {
          // 非叶子节点
          if (isArrayItems) {
            // 数组的items节点
            return currentSchema.items
              ? this.isComplexType(currentSchema.items, 0, 1, 2, 4)
                ? 16 * currentIndex
                : 16 * (currentIndex + 1)
              : 16 * currentIndex;
          } else {
            return 16 * (currentIndex - 1);
          }
        }
      }
    } else {
      // 引用
      if (currentIndex == 1) {
        // 根节点
        return 16;
      } else {
        // 非根节点
        if (this.isComplexType(currentSchema, 3)) {
          // 叶子节点
          return 16 * (currentIndex + 1);
        } else {
          // 非叶子节点
          return isArrayItems == "items"
            ? 16 * (currentIndex + 1)
            : 16 * currentIndex;
        }
      }
    }
  }
  /**
   * 添加鼠标滑动监听事件
   * @param {*} dom
   */
  addMouseEventListeners(dom) {
    dom.addEventListener("mouseenter", function (e) {
      Array.prototype.forEach.call(e.target.childNodes, (subDom) => {
        if (!subDom.classList) return;
        if (
          subDom.classList.contains("quote-drag") ||
          subDom.classList.contains("quote-header")
        ) {
          subDom.style.display = "none";
          subDom.style.display = "flex";
        } else if (subDom.classList.contains("quote-box")) {
          subDom.style.opacity = 1;
        }
      });
    });
    dom.addEventListener("mouseleave", function (e) {
      Array.prototype.forEach.call(e.target.childNodes, (subDom) => {
        if (!subDom.classList) return;
        if (
          subDom.classList.contains("quote-drag") ||
          subDom.classList.contains("quote-header")
        ) {
          subDom.style.display = "none";
        } else if (subDom.classList.contains("quote-box")) {
          subDom.style.opacity = 0;
        }
      });
    });
  }
  /**
   * 使用js为引用修改样式
   * @param {*} dom
   */
  dragDomStyle(dom, index) {
    Array.prototype.forEach.call(dom.childNodes, (subDom) => {
      if (!subDom.classList) return;
      if (subDom.classList.contains("quote-box")) {
        subDom.style.left = index * 16 + 11 + "px";
      }
      if (subDom.classList.contains("quote-drag")) {
        subDom.style.transform = "translate(" + index * 16 + "px,-50%)";
      }
    });
  }
  /**
   * 节点类型切换,更新节点数据结构
   * @param {*} type
   * @param {*} ref
   * @param {*} schema
   */
  handleChangeType(type, sign, schema) {
    let _this = this;
    return getValueBySign(sign);
    function getValueBySign(key) {
      switch (key) {
        case "item":
          return {
            ...schema,
            type: "array",
            items: getValueByType(type, { ...schema }.items),
          };
        case "key":
          return {
            ...schema,
            patternProperties: {
              [_this.dictKeyMap(type)]: { ..._this.getDictValue(schema) },
            },
          };
        case "value":
          return {
            ...schema,
            patternProperties: {
              [_this.dictKeyMap(_this.getDictKeyAndValueType(schema).keyType)]:
                getValueByType(
                  type,
                  { ...schema }.patternProperties[
                    _this.dictKeyMap(
                      _this.getDictKeyAndValueType(schema).keyType
                    )
                  ]
                ),
            },
          };
        default:
          return getValueByType(type, { ...schema });
      }
      function getValueByType(nodeType, jsonSchema) {
        // 删除之前的属性
        _this.deleteSchemaAttr(jsonSchema);
        switch (nodeType) {
          case "string":
          case "number":
          case "integer":
          case "boolean":
          case "null":
          case "any":
            return {
              ...jsonSchema,
              type:
                nodeType == "any"
                  ? [
                      "string",
                      "integer",
                      "boolean",
                      "array",
                      "object",
                      "number",
                      "null",
                    ]
                  : nodeType,
            };
          case "array":
            return {
              ...jsonSchema,
              type: "array",
              items: {
                type: "string",
              },
            };
          case "object":
            return {
              ...jsonSchema,
              type: "object",
              properties: {},
              "x-apifox-orders": [],
            };
          case "dictionary":
            return {
              ...jsonSchema,
              type: "object", // 可视化时显示为字典，但是实际类型为object
              properties: {},
              patternProperties: {
                "^[a-zA-Z_][a-zA-Z0-9_]*$": {
                  type: "string",
                },
              },
              "x-apifox-orders": [],
            };
        }
      }
    }
  }

  deleteSchemaAttr(jsonSchema) {
    // number和integer的高级设计属性
    delete jsonSchema.format;
    delete jsonSchema.exclusiveMaximum;
    delete jsonSchema.exclusiveMinimum;
    delete jsonSchema.maximum;
    delete jsonSchema.minimum;
    // object的属性
    delete jsonSchema.properties;
    delete jsonSchema.required;
    delete jsonSchema["x-apifox-orders"];
    // dictionary的属性
    delete jsonSchema.patternProperties;
    // array的属性
    delete jsonSchema.items;
    // 引用模型的属性
    delete jsonSchema.$ref;
    delete jsonSchema["x-apifox-refs"];
  }

  /**
   * 解析带有引用的schema为不带引的schema
   * @param {*} currentSchema
   * @param {*} jsonSchema
   * @returns
   */
  resolveRefs(currentSchema, jsonSchema) {
    // 分离全局和模型数据存储
    const globalSchemaMap = new Map();
    const modelSchemaMap = new Map();

    const buildMap = (nodes) => {
      nodes.forEach((node) => {
        // 同时收集globalDataId和modelDataId
        if (node.data?.globalDataId) {
          globalSchemaMap.set(
            String(node.data.globalDataId),
            node.data.jsonSchemaData
          );
        }
        if (node.data?.modelDataId) {
          modelSchemaMap.set(
            String(node.data.modelDataId),
            node.data.jsonSchemaData
          );
        }
        if (node.children) buildMap(node.children);
      });
    };
    buildMap(jsonSchema);
    // 调整正则表达式捕获引用类型
    const refPattern = /#\/(global)?definitions\/(\d+)/i;

    const resolve = (obj) => {
      if (obj && typeof obj === "object") {
        if (obj.$ref) {
          const match = obj.$ref.match(refPattern);
          if (match) {
            const isGlobal = !!match[1]; // 通过捕获组判断引用类型
            const defKey = match[2];
            // 根据引用类型选择对应数据源
            const targetMap = isGlobal ? globalSchemaMap : modelSchemaMap;
            if (targetMap.has(defKey)) {
              return resolve(JSON.parse(targetMap.get(defKey)));
            }
          }
        }

        if (obj["x-apifox-refs"]) {
          for (const key in obj["x-apifox-refs"]) {
            const refObj = obj["x-apifox-refs"][key];
            const match = refObj?.$ref?.match(refPattern);
            if (match) {
              const isGlobal = !!match[1];
              const defKey = match[2];
              const targetMap = isGlobal ? globalSchemaMap : modelSchemaMap;
              if (targetMap.has(defKey)) {
                const refSchema = resolve(JSON.parse(targetMap.get(defKey)));
                delete obj["x-apifox-refs"][key];
                const keyIndex = obj["x-apifox-orders"].indexOf(key);
                obj["x-apifox-orders"].splice(
                  keyIndex,
                  1,
                  ...(refSchema["x-apifox-orders"] || [])
                );
                // obj.properties = { ...refSchema.properties, ...obj.properties };
                const entries = Object.entries(obj.properties);
                entries.splice(
                  keyIndex,
                  0,
                  ...Object.entries(refSchema.properties)
                );
                obj.properties = Object.fromEntries(entries);
              }
            }
          }
        }
        // 保持递归处理
        for (const prop in obj) {
          if (typeof obj[prop] === "object") {
            obj[prop] = resolve(obj[prop]);
          }
        }
      }
      return obj;
    };
    return resolve(JSON.parse(JSON.stringify(currentSchema)));
  }

  /**
   * 删除schema中的临时数据
   * @param {*} schema
   */
  removeTmpProperties(schema) {
    const cleanSchema = (node) => {
      if (!node || typeof node !== "object") return node;
      // 处理嵌套 properties
      if (node.properties) {
        const tmpKeys = new Set();

        // 递归处理子属性并标记待删除键
        for (const [key, value] of Object.entries(node.properties)) {
          if (value["x-tmp-pending-properties"] === true) {
            tmpKeys.add(key);
          } else {
            node.properties[key] = cleanSchema(value); // 递归清理子节点
          }
        }

        // 删除标记节点
        tmpKeys.forEach((k) => delete node.properties[k]);

        // 清理关联数组
        ["required", "x-apifox-orders"].forEach((arrKey) => {
          if (Array.isArray(node[arrKey])) {
            node[arrKey] = node[arrKey].filter((k) => !tmpKeys.has(k));
            if (node[arrKey].length === 0) delete node[arrKey];
          }
        });
      }

      return node;
    };

    return cleanSchema(JSON.parse(JSON.stringify(schema))); // 深拷贝后处理
  }

  /**
   * 查找所有字典项路径并生成对应的uiSchema配置（嵌套结构）
   * @param {object} schema - JSON Schema对象
   * @param {string[]} [path=[]] - 当前路径数组（内部递归使用）
   * @returns {object} - 生成的嵌套uiSchema对象
   */
  generateNestedDictUISchema(schema, path = []) {
    let uiSchema = {};

    if (this.isComplexType(schema, 4)) {
      // 创建当前层级的uiSchema配置
      let current = uiSchema;
      for (let i = 0; i < path.length; i++) {
        const key = path[i];
        current[key] = current[key] || {};
        if (i === path.length - 1) {
          current[key]["ui:field"] = "DictionaryField";

          // 处理patternProperties中的字典项
          if (schema.patternProperties) {
            current[key].patternProperties =
              current[key].patternProperties || {};
            for (const [pattern, patternSchema] of Object.entries(
              schema.patternProperties
            )) {
              if (this.isComplexType(patternSchema, 4)) {
                current[key].patternProperties[pattern] = {
                  "ui:field": "DictionaryField",
                };

                // 递归处理嵌套的patternProperties
                const nested = this.generateNestedDictUISchema(patternSchema, [
                  ...path,
                  "patternProperties",
                  pattern,
                ]);
                current[key].patternProperties[pattern] = this.deepMerge(
                  current[key].patternProperties[pattern],
                  nested.patternProperties?.[pattern] || {}
                );
              }
            }
          }
        }
        current = current[key];
      }
      return uiSchema;
    }

    // 递归处理对象属性
    if (this.isComplexType(schema, 1)) {
      for (const [key, property] of Object.entries(schema.properties)) {
        const nested = this.generateNestedDictUISchema(property, [
          ...path,
          key,
        ]);
        uiSchema = this.deepMerge(uiSchema, nested);
      }
    }

    // 递归处理数组项
    if (this.isComplexType(schema, 0)) {
      const nested = this.generateNestedDictUISchema(schema.items, [
        ...path,
        "items",
      ]);
      uiSchema = this.deepMerge(uiSchema, nested);
    }

    return uiSchema;
  }

  /**
   * 深度合并两个对象
   */
  deepMerge(target, source) {
    for (const key in source) {
      if (source.hasOwnProperty(key)) {
        if (
          typeof source[key] === "object" &&
          source[key] !== null &&
          typeof target[key] === "object" &&
          target[key] !== null
        ) {
          target[key] = this.deepMerge(target[key], source[key]);
        } else {
          target[key] = source[key];
        }
      }
    }
    return target;
  }

  /**
   * 获取原始类型
   * @param {*} schema
   */
  getOriginalType(schema) {
    // 区分对象和字典
    if (
      (schema.type == "object" &&
        !schema.hasOwnProperty("patternProperties")) ||
      (Array.isArray(schema.type) &&
        schema.type.length == 2 &&
        schema.type.includes("object"))
    ) {
      return "object";
    } else if (this.isDictType(schema)) {
      return "dictionary";
    } else {
      return this.getOriginalTypeWhenTypeIncludeMulti(schema.type);
    }
  }

  /**
   * 当type是包含多个时，还原原始选择的类型
   * 当非any类型并可以为null时 type的值为["string", "null"]
   * 当是any类型时 type的值为["string","integer","boolean","array","object","number","null"]
   * @param {*} type
   */
  getOriginalTypeWhenTypeIncludeMulti(type) {
    if (Array.isArray(type)) {
      if (type.length == 2) {
        return type[0];
      }
      if (type.length > 2) {
        return "any";
      }
    } else {
      return type;
    }
  }

  /**
   * 根据当前节点的类别判断是否显示高级选项
   * 引用类型、integer、number显示高级选项
   * @param {*} schema
   */
  displayAdvanced(schema) {
    if (
      schema.$ref != undefined ||
      schema.type == "integer" ||
      schema.type == "number"
    ) {
      return true;
    } else if (
      Array.isArray(schema.type) &&
      schema.type.length == 2 &&
      (schema.type.includes("integer") || schema.type.includes("number"))
    ) {
      return true;
    } else {
      return false;
    }
  }

  /**
   * 检查JSON Schema中所有层级的title和description是否存在且不为空
   * @param {object} schema - 要检查的JSON Schema对象
   * @returns {boolean} - 是否所有title和description都存在且不为空
   */
  checkTitlesAndDescriptions(schema) {
    // 基础检查：当前对象必须有title和description且不为空
    if (
      !schema ||
      typeof schema.title !== "string" ||
      !schema.title.trim() ||
      typeof schema.description !== "string" ||
      !schema.description.trim()
    ) {
      return false;
    }

    // 检查properties中的每个属性
    if (schema.properties) {
      for (const key in schema.properties) {
        if (!this.checkTitlesAndDescriptions(schema.properties[key])) {
          return false;
        }
      }
    }

    // 检查数组items（如果存在）
    // if (schema.items && !this.checkTitlesAndDescriptions(schema.items)) {
    //   return false;
    // }

    // 所有检查通过
    return true;
  }
}
export default jsonSchemaToolHandle;
